home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 001-025 / disk_005 / freemapsrc / freemap.c next >
C/C++ Source or Header  |  1992-05-06  |  12KB  |  505 lines

  1. /*
  2.  *
  3.  *    DISCLAIMER:
  4.  *
  5.  *    This program is provided as a service to the programmer
  6.  *    community to demonstrate one or more features of the Amiga
  7.  *    personal computer.  These code samples may be freely used
  8.  *    for commercial or noncommercial purposes.
  9.  * 
  10.  *     Commodore Electronics, Ltd ("Commodore") makes no
  11.  *    warranties, either expressed or implied, with respect
  12.  *    to the program described herein, its quality, performance,
  13.  *    merchantability, or fitness for any particular purpose.
  14.  *    This program is provided "as is" and the entire risk
  15.  *    as to its quality and performance is with the user.
  16.  *    Should the program prove defective following its
  17.  *    purchase, the user (and not the creator of the program,
  18.  *    Commodore, their distributors or their retailers)
  19.  *    assumes the entire cost of all necessary damages.  In 
  20.  *    no event will Commodore be liable for direct, indirect,
  21.  *    incidental or consequential damages resulting from any
  22.  *    defect in the program even if it has been advised of the 
  23.  *    possibility of such damages.  Some laws do not allow
  24.  *    the exclusion or limitation of implied warranties or
  25.  *    liabilities for incidental or consequential damages,
  26.  *    so the above limitation or exclusion may not apply.
  27.  *
  28.  */
  29.  
  30.  
  31. /*****************************************************************************
  32.  *
  33.  * FreeMap program creates a visual diagram of free memory
  34.  *
  35.  * =Robert J. Mical=
  36.  * 9 January 1986
  37.  * 
  38.  * Copyright (C) 1986, COMMODORE-AMIGA, INC.
  39.  * All Rights Reserved
  40.  *
  41.  ****************************************************************************/
  42.  
  43. #include "freemap.h"
  44.  
  45. #define SCREENWIDTH    320
  46. #define SCREENHEIGHT    36
  47.  
  48. #define STARTLINE    6
  49. #define STARTCOLUMN    (2 + 4)
  50.  
  51. #define LEFTOFFSET    6
  52.  
  53. #define MENU_INFO    2
  54. #define MENU_REDISPLAY    1
  55. #define MENU_QUIT    0
  56.  
  57. #define SCREENBYTEWIDTH    40
  58. #define MAPBYTEWIDTH    32    /* must be a power of two */
  59. #define MAX_BLOCK_COUNT    ((512 * 1024) >> 6)
  60.  
  61. struct IntuitionBase *IntuitionBase;
  62. struct GfxBase *GfxBase;
  63. extern struct ExecBase *SysBase;
  64.  
  65. struct TextAttr SafeFont =
  66.     {
  67.     "topaz.font",
  68.     8,
  69.     0,
  70.     0,
  71.     };
  72.  
  73.  
  74. struct IntuiText PleaseText = 
  75.     {
  76.     0, 1,
  77.     JAM2,
  78.     1, 1,
  79.     NULL,
  80.     "Please",
  81.     NULL,
  82.     };
  83.  
  84.  
  85. struct MenuItem PleaseItem =
  86.     {
  87.     NULL,
  88.     0, 0,
  89.     88, 9,
  90.     ITEMTEXT | ITEMENABLED | HIGHCOMP,
  91.     0,
  92.     (APTR)&PleaseText,
  93.     NULL,
  94.     0,
  95.     NULL,
  96.     NULL,
  97.     };
  98.  
  99.  
  100. struct Menu MapMenus[] =
  101.     {
  102.     {
  103.     NULL,
  104.     10, 0,
  105.     48, 0,
  106.     MENUENABLED,
  107.     "Info",
  108.     &PleaseItem,
  109.     },
  110.  
  111.     {
  112.     &MapMenus[0],
  113.     58, 0,
  114.     88, 0,
  115.     MENUENABLED,
  116.     "Redisplay",
  117.     &PleaseItem,
  118.     },
  119.  
  120.     {
  121.     &MapMenus[1],
  122.     146, 0,
  123.     48, 0,
  124.     MENUENABLED,
  125.     "Quit",
  126.     &PleaseItem,
  127.     },
  128.  
  129.     };
  130.  
  131.  
  132. struct NewScreen MapScreen =
  133.     {
  134.     0, 200 - SCREENHEIGHT,
  135.     SCREENWIDTH, SCREENHEIGHT, 1,
  136.     0, 1,
  137.     NULL,
  138.     CUSTOMSCREEN,
  139.     &SafeFont,
  140.     NULL,
  141.     NULL,
  142.     NULL,
  143.     };
  144.  
  145.  
  146. struct NewWindow MapWindow =
  147.     {
  148.     LEFTOFFSET, 0,
  149.     (MAPBYTEWIDTH << 3) + 4, SCREENHEIGHT,
  150.     -1, -1,
  151.     MENUPICK | MENUVERIFY,
  152.     SMART_REFRESH | BACKDROP | BORDERLESS | NOCAREREFRESH,
  153.     NULL, 
  154.     NULL, 
  155.     NULL, 
  156.     NULL, 
  157.     NULL, 
  158.     0, 0, 0, 0,
  159.     CUSTOMSCREEN,
  160.     };
  161.     
  162.     
  163. struct Screen *MyScreen;
  164. struct Window *MyWindow;
  165. SHORT BitsAvailable;
  166. SHORT BlockCount;
  167. BYTE BitsValue;
  168. SHORT WidthIndex;
  169. UBYTE *MemBlock;
  170. UBYTE *MapPointer;
  171.  
  172. ShiftMask[8] =
  173.     {
  174.     0xFF,
  175.     0X01,
  176.     0x03,
  177.     0x07,
  178.     0x0F,
  179.     0x1F,
  180.     0x3F,
  181.     0x7F,
  182.     };
  183.  
  184.  
  185. RestartWindow()
  186. /* This routine clears the window and then draws the border */
  187. {
  188.     SetRast(MyWindow->RPort, 0);
  189.     Move(MyWindow->RPort, 0, 0);
  190.     Draw(MyWindow->RPort, 0, SCREENHEIGHT - 1);
  191.     Draw(MyWindow->RPort, (MAPBYTEWIDTH << 3)+4-1, SCREENHEIGHT - 1);
  192.     Draw(MyWindow->RPort, (MAPBYTEWIDTH << 3) + 4 - 1, 0);
  193.     Draw(MyWindow->RPort, 0, 0);
  194. }
  195.  
  196.  
  197. BumpMapPointer()
  198. /* This routine bumps the MapPointer variable, which variable contains the
  199.  * pointer to the byte in the Screen's BitMap which is to receive the
  200.  * next FreeMap bits.
  201.  */
  202. {
  203.     WidthIndex++;
  204.     if (WidthIndex == MAPBYTEWIDTH)
  205.     {
  206.     /* We're at the right edge of the map window, so skip ahead
  207.      * to the left edge of the next line
  208.      */
  209.     WidthIndex = 0;
  210.     MapPointer += (SCREENBYTEWIDTH - MAPBYTEWIDTH + 1);
  211.     }
  212.     else MapPointer++;
  213. }
  214.  
  215.  
  216. ShiftInBits(bitcount)
  217. SHORT bitcount;
  218. /* This routine "shifts" the next set of bits into the memory map */
  219. {
  220.     SHORT shift, bytecount;
  221.  
  222.     if (BitsAvailable & 0x7)
  223.     {
  224.     /* There's less than a whole byte available, so we must start 
  225.      * by shifting.  Get the shift amount, which will be either all
  226.      * of the bits that are available, or the block count if it's less
  227.      * than the count of the available bits
  228.      */
  229.     if (bitcount > BitsAvailable) shift = BitsAvailable;
  230.     else shift = bitcount;
  231.  
  232.     /* Shift the current contents of this byte of the map 
  233.      * out of the way of our new bits.
  234.      */
  235.     *MapPointer <<= shift;
  236.     
  237.     /* The above shift shifts zero bits in from the right.
  238.      * If the current BitsValue is clear, leave them zero, else set our
  239.      * new bits.
  240.      */
  241.     if (BitsValue) *MapPointer |= ShiftMask[shift];
  242.     
  243.     /* Reduce the block count by the number of bits we just arranged */
  244.     bitcount -= shift;
  245.     
  246.     /* if we've used up this memory map byte, advance to the next one */
  247.     if ((BitsAvailable -= shift) == 0)
  248.         {
  249.         BitsAvailable = 8;
  250.         BumpMapPointer();
  251.         }
  252.  
  253.     }
  254.  
  255.     /* Now that we've taken care of any partially completed Map bytes,
  256.      * let's check for any whole bytes that we can set (speed!)
  257.      */
  258.     bytecount = bitcount >> 3;
  259.     while (bytecount)
  260.     {
  261.     *MapPointer = BitsValue;
  262.     BumpMapPointer();
  263.     bytecount--;
  264.     }
  265.  
  266.     /* Finally, do any remaining bitcount bits to be set */
  267.     if (bitcount &= 0x7)
  268.     {
  269.     *MapPointer = BitsValue;    /* Cheating, in a sense, but FAST! */
  270.     BitsAvailable = 8 - bitcount;
  271.     }
  272. }
  273.  
  274.  
  275. SHORT FindFreeBlock()
  276. /* This routine feels through the memory-free list, looking for a block
  277.  * of free memory that is big enough to qualify as being a block.
  278.  * A block starts on 64-byte boundaries and is 64-bytes wide.  For a
  279.  * block to be considered "free" all of the 64 bytes must be free
  280.  */
  281. {
  282.     SHORT firstwholeblock, nextrealblock;
  283.  
  284.     FOREVER
  285.     {
  286.     if (MemBlock == 0) return(0);
  287.     firstwholeblock = (LONG)(MemBlock + 63) >> 6;
  288.     nextrealblock = (LONG)( MemBlock 
  289.         + ((struct MemChunk *)MemBlock)->mc_Bytes ) >> 6;
  290.  
  291.     MemBlock = (UBYTE *)((struct MemChunk *)MemBlock)->mc_Next;
  292.  
  293.     if (firstwholeblock < nextrealblock)
  294.         {
  295.         BlockCount = nextrealblock - firstwholeblock;
  296.         return(firstwholeblock);
  297.         }
  298.     }
  299. }
  300.  
  301.  
  302.  
  303. SetTimer(sec, micro, timermsg)
  304. ULONG sec, micro;
  305. struct IOStdReq *timermsg;
  306. /* This routine simply sets the timer to interrupt us after secs.micros */
  307. {
  308.     timermsg->io_Command = TR_ADDREQUEST;    /* add a new timer request */
  309.     timermsg->io_Actual = sec;    /* seconds */
  310.     timermsg->io_Length = micro;    /* microseconds */
  311.     SendIO(timermsg);    /* post a request to the timer */
  312. }
  313.  
  314.  
  315.  
  316. main()
  317. {
  318.     struct MsgPort *timerport;
  319.     struct IOStdReq *timermsg;
  320.     struct MemHeader *MemHeader;
  321.     SHORT NextFreeBlock, NextTakenBlock;
  322.     ULONG wakeupbits, timerbit, windowbit;
  323.     struct IntuiMessage *message;
  324.     ULONG class;
  325.     USHORT code;
  326.     BOOL Redisplay;
  327.  
  328.  
  329.     if ((IntuitionBase = (struct IntuitionBase *)OpenLibrary(
  330.         "intuition.library", 0)) == 0)
  331.     {
  332.     printf("NO LIBRARY");
  333.     goto EXITING;
  334.     }
  335.  
  336.     if ((GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0)) == 0)
  337.     {
  338.     printf("NO LIBRARY");
  339.     goto EXITING;
  340.     }
  341.  
  342.     if ((MyScreen = (struct Screen *)OpenScreen(&MapScreen)) == NULL)
  343.     {
  344.     printf("NO SCREEN");
  345.     goto EXITING;
  346.     }
  347.  
  348.     ShowTitle(MyScreen, FALSE);
  349.     SetRGB4(&MyScreen->ViewPort, 0, 15, 12, 8);
  350.     SetRGB4(&MyScreen->ViewPort, 1, 8, 0, 0);
  351.  
  352.     MapWindow.Screen = MyScreen;    
  353.     if ((MyWindow = (struct Window *)OpenWindow(&MapWindow)) == NULL)
  354.     {
  355.     printf("NO WINDOW");
  356.     goto EXITING;
  357.     }
  358.     SetMenuStrip(MyWindow, &MapMenus[2]);
  359.     SetFont(MyWindow->RPort, OpenFont(&SafeFont));
  360.  
  361.     Move(&MyScreen->RastPort, (MAPBYTEWIDTH << 3) + 8 + 4, 18);
  362.     Text(&MyScreen->RastPort, "512K", 4);
  363.     Move(&MyScreen->RastPort, (MAPBYTEWIDTH << 3) + 8 + 4, 26);
  364.     Text(&MyScreen->RastPort, "MEMORY", 6);
  365.     Move(&MyScreen->RastPort, (MAPBYTEWIDTH << 3) + 8 + 4, 34);
  366.     Text(&MyScreen->RastPort, "MAP", 3);
  367.     RestartWindow();
  368.  
  369.     timerport = (struct MsgPort *)CreatePort(0, 0);
  370.     if (timerport == 0) goto EXITING;
  371.  
  372.     timermsg = (struct IOStdReq *)CreateStdIO(timerport);
  373.     if (timermsg == 0) goto EXITING;
  374.  
  375.     if (OpenDevice(TIMERNAME, UNIT_VBLANK, timermsg, 0) != 0)
  376.     goto EXITING;
  377.     
  378.     timerbit = 1 << timerport->mp_SigBit;
  379.     windowbit = 1 << MyWindow->UserPort->mp_SigBit;
  380.  
  381.     SetTimer(2, 0, timermsg);
  382.  
  383.     Redisplay = TRUE;
  384.  
  385.     FOREVER
  386.     {
  387.     if (Redisplay)
  388.         {
  389.         /* This program draws the memory map information right into
  390.          * the BitMap of the Screen, rather than using the graphics 
  391.          * support library routines to draw into the Window. 
  392.          * There is nothing illegal or immoral about doing this, but
  393.          * is does require a thorough knowledge of how Intuition and
  394.          * the graphics library create and manipulate the display.
  395.          * In other words, this is *not* something that the novice 
  396.          * will want to do lightly, but the soon-to-be-expert may
  397.          * want to examine as an example of how to do meta-graphics
  398.          * in the Amiga window environment.
  399.          */
  400.         MapPointer = MyScreen->RastPort.BitMap->Planes[0];
  401.         MapPointer += (SCREENBYTEWIDTH * 2 + 1);
  402.  
  403.         Forbid();
  404.  
  405.         do
  406.         MemHeader = (struct MemHeader *)SysBase->MemList.lh_Head;
  407.         while ((MemHeader->mh_Attributes & MEMF_CHIP) == 0);
  408.  
  409.         MemBlock = (UBYTE *)MemHeader->mh_First;
  410.     
  411.         BitsAvailable = 8;
  412.         WidthIndex = 0;
  413.         NextTakenBlock = 0;
  414.  
  415.         do 
  416.         {
  417.         if (NextFreeBlock = FindFreeBlock())
  418.             {
  419.             BitsValue = 0;
  420.             ShiftInBits(NextFreeBlock - NextTakenBlock);
  421.             BitsValue = -1;
  422.             ShiftInBits(BlockCount);
  423.             NextTakenBlock = NextFreeBlock + BlockCount;
  424.             }
  425.         else ShiftInBits(MAX_BLOCK_COUNT - NextTakenBlock);
  426.         }
  427.         while (MemBlock);
  428.  
  429.         if (NextTakenBlock < MAX_BLOCK_COUNT)
  430.         {
  431.         BitsValue = 0;
  432.         ShiftInBits(MAX_BLOCK_COUNT - NextTakenBlock);
  433.         }
  434.         Permit();
  435.         }
  436.  
  437.     wakeupbits = Wait(timerbit | windowbit);
  438.  
  439.     if (wakeupbits & timerbit)
  440.         {
  441.         GetMsg(timerport);    /* this does nothing more than "clear" */
  442.         SetTimer(2, 0, timermsg);
  443.         }
  444.  
  445.     if (wakeupbits & windowbit)
  446.         {
  447.         message = (struct IntuiMessage *)GetMsg(MyWindow->UserPort);
  448.         class = message->Class;
  449.         code = message->Code;
  450.         ReplyMsg(message);
  451.         switch (class)
  452.         {
  453.         case MENUVERIFY:
  454.             Redisplay = FALSE;
  455.             break;
  456.         case MENUPICK:
  457.             switch (MENUNUM(code))
  458.             {
  459.             case MENU_INFO:
  460.                 RestartWindow();
  461.                 Move(MyWindow->RPort, 
  462.                     STARTCOLUMN, STARTLINE);
  463.                 Text(MyWindow->RPort,
  464.                     "Each pixel represents 64 bytes.", 31);
  465.                 Move(MyWindow->RPort, 
  466.                     STARTCOLUMN + 20, STARTLINE + 9);
  467.                 Text(MyWindow->RPort,
  468.                     "If all bytes are free, the", 26);
  469.                 Move(MyWindow->RPort, 
  470.                     STARTCOLUMN, STARTLINE + 18);
  471.                 Text(MyWindow->RPort,
  472.                     "pixel is dark, else it's light.", 31);
  473.                 Move(MyWindow->RPort, 
  474.                     STARTCOLUMN + 20, STARTLINE + 28);
  475.                 Text(MyWindow->RPort,
  476.                     "This trinket by  =RJMical=", 26);
  477.                 break;
  478.             case MENU_REDISPLAY:
  479.                 RestartWindow();
  480.             case NOMENU:
  481.                 Redisplay = TRUE;
  482.                 break;
  483.             case MENU_QUIT:
  484.                 goto EXITING;
  485.             }
  486.         }
  487.         }
  488.     }
  489.  
  490. EXITING:
  491.     if (MyWindow) CloseWindow(MyWindow);
  492.     if (MyScreen) CloseScreen(MyScreen);
  493.     if (timerport)
  494.     {
  495.     Wait(timerbit);
  496.     GetMsg(timerport);
  497.  
  498.     CloseDevice(timermsg);
  499.     DeleteStdIO(timermsg);
  500.     DeletePort(timerport);
  501.     }
  502. }
  503.  
  504.  
  505.